package com.skyworth.web.wechat.controller;

import com.skyworth.utils.CookieUtil;
import com.skyworth.utils.RequestUtil;
import com.skyworth.utils.StrUtil;
import com.skyworth.utils.TimeUtil;
import com.skyworth.web.admin.table.service.ITableService;
import com.skyworth.web.common.Constants;
import com.skyworth.web.order.domain.OrderModel;
import com.skyworth.web.order.domain.ParentOrderModel;
import com.skyworth.web.order.service.NewOrderService;
import com.skyworth.web.wechat.common.AppSecretInfo;
import com.skyworth.web.wechat.common.JsSign;
import com.skyworth.web.wechat.common.MessageParse;
import com.skyworth.web.wechat.common.WxConstant;
import com.skyworth.web.wechat.engin.ServerEngin;
import com.skyworth.web.wechat.entity.AccessTokenModel;
import com.skyworth.web.wechat.entity.PayDetailModel;
import com.skyworth.web.wechat.entity.TableBindModel;
import com.skyworth.web.wechat.entity.TicketModel;
import com.skyworth.web.wechat.protocol.NotifyMsg;
import com.skyworth.web.wechat.protocol.ProcessMsg;
import com.skyworth.web.wechat.protocol.ScanPayReq;
import com.skyworth.web.wechat.protocol.ScanPayRes;
import com.skyworth.web.wechat.service.AccessTokenService;
import com.skyworth.web.wechat.service.TableBindService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by yuhaichao on 2016/8/24.
 */
@Controller
@RequestMapping("wechat")
public class WxController {

    private static final Logger log = LoggerFactory.getLogger(WxController.class);

    @Autowired
    private AccessTokenService accessTokenService;

    @Autowired
    private NewOrderService newOrderService;

    @Autowired
    private ITableService iTableService;

    @Autowired
    private TableBindService tableBindService;

    @Autowired
    private ProcessMsg processMsg;



    @RequestMapping("/test")
    @ResponseBody
    public String test(HttpServletRequest request){
        String str = request.getQueryString();
        System.out.println(str);
        /*TableBindModel tbm = new TableBindModel();
        tbm.setTableId(123);
        tbm.setUserId("aaa");
        tableBindService.saveTableBind(tbm);

        return tableBindService.getTableBindByUserId("aaa");*/
        return str;
    }

    @RequestMapping("/getBindTable")
    @ResponseBody
    public TableBindModel getBindTable(HttpServletRequest request){
        String userId = CookieUtil.getCookie(AppSecretInfo.appId+"_uid",request);
        if(userId!=null && !"".equals(userId)) {
            return tableBindService.getTableBindByUserId(userId);
        }
        return null;
    }

    @RequestMapping("/wxToken")
    @ResponseBody
    public String weixinToken(HttpServletRequest request) {
        try {
            String method = request.getMethod();
            System.out.println("method:"+method);
            //ProcessMsg pm = new ProcessMsg();
            if ("POST".equals(method.toUpperCase())) {
                return processMsg.process(request);
            } else {
                return processMsg.checkToken(request);
            }
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return null;
    }

    @RequestMapping("/index.html")
    public String index(HttpServletRequest request, HttpServletResponse response, String from,String code, Model model){
        String error_msg="授权认证失败，请稍后再试。";
        try {
            String cookieUid = CookieUtil.getCookie(AppSecretInfo.appId+"_uid",request);
            CookieUtil.setCookie("appkey", AppSecretInfo.appId,response);
            if(cookieUid!=null && !"".equals(cookieUid)){
                CookieUtil.setCookie(AppSecretInfo.appId+"_uid", cookieUid,response);
            }else if(code!=null && !"".equals(code)){
                Map<Object,Object> openidMap = ServerEngin.getInstance().getOauthUserId(code,AppSecretInfo.appId,AppSecretInfo.appSecret);
                if(openidMap!=null){
                    cookieUid=StrUtil.objectToString(openidMap.get("openid"));

                    if(cookieUid!=null && !"".equals(cookieUid)){
                        CookieUtil.setCookie(AppSecretInfo.appId+"_uid", cookieUid,response);
                    }
                }

            }else{
                String orderUrl= WxConstant.WX_DOMAIN+"wechat/index.html";
                //String queryStr = request.getQueryString();
                if("orders".equals(from)){
                    orderUrl= WxConstant.WX_DOMAIN+"wechat/index.html?from=orders";
                }
                try {
                    orderUrl = URLEncoder.encode(orderUrl, "utf-8");
                } catch (UnsupportedEncodingException e) {
                }
                String orderMenuUrl=WxConstant.OAUTH_URL;
                orderMenuUrl=orderMenuUrl.replace("${appid}", AppSecretInfo.appId);
                orderMenuUrl=orderMenuUrl.replace("${redirect_uri}", orderUrl);

                return "redirect:"+orderMenuUrl;
            }

            if(cookieUid!=null && !"".equals(cookieUid)){
                /*OrderModel om =orderService.getLastOrder(cookieUid);
                if(om!=null && om.id>0){
                    CookieUtil.setCookie("unpayed", String.valueOf(om.id),response);
                }else{
                    CookieUtil.deleteCookie("unpayed",response);
                }*/

                OrderModel cartModel = newOrderService.getOrderCart(cookieUid);
                if(cartModel!=null && cartModel.id>0){
                    long cartOrderId = 0;
                    try {
                        cartOrderId = Long.parseLong(CookieUtil.getCookie("cartOrderId", request));
                    }catch (Exception e){

                    }
                    if(cartOrderId==cartModel.id) {
                        CookieUtil.setCookie("hascart", "1", response);
                    }
                }else{
                    //CookieUtil.deleteCookie("cartOrderId",response);
                    CookieUtil.deleteCookie("hascart",response);
                }

                TableBindModel tableBindModel = tableBindService.getTableBindByUserId(cookieUid);
                if(tableBindModel!=null && tableBindModel.getTableId()>0){
                    CookieUtil.setCookie("bindtabid", String.valueOf(tableBindModel.getTableId()),response);
                }else{
                    CookieUtil.deleteCookie("bindtabid",response);
                }

                CookieUtil.setCookie(Constants.COOKIE_STORE_ID,"6",response);

                final String userId = cookieUid;
                new Thread(){
                    public void run(){
                        accessTokenService.saveWxUserInfo(userId);
                    }
                }.start();
                if(code!=null && !"".equals(code) && "orders".equals(from)){
                    return "redirect:/wechat/index.html#action=orders";
                }else {
                    return "m/index";
                }
            }

        }catch (Exception e){
            log.error(e.getMessage());
        }
        model.addAttribute("error_msg",error_msg);
        return "m/error";
    }

    @RequestMapping("/payQrCode/{tableId}")
    @ResponseBody
    public Map<String,Object> payQrCode(@PathVariable long tableId,HttpServletRequest request){
        try{
            Map<String,Object> codeMap = new HashMap<>();
            String pkg = processPayOrder(tableId,null,"NATIVE",request);
            if(pkg==null || "".equals(pkg)){
                codeMap.put("status","error");
                return codeMap;
            }

            codeMap.put("qrCodeUrl",pkg);
            return codeMap;

        }catch(Exception e){
            log.error(e.getMessage());
        }
        return null;
    }

    @RequestMapping("/payOrder")
    @ResponseBody
    public Map<String,Object> payOrder(HttpServletRequest request){
        try{
            String userId = CookieUtil.getCookie(AppSecretInfo.appId+"_uid",request);
            String bindtabid = CookieUtil.getCookie("bindtabid",request);

            long tableId= Long.parseLong(bindtabid);

                String pkg = processPayOrder(tableId,userId,"JSAPI",request);
            if(pkg==null || "".equals(pkg)){
                return null;
            }
                Map<String,Object> signMap = JsSign.paySign(pkg,AppSecretInfo.appId);
               return signMap;


        }catch(Exception e){
            log.error(e.getMessage());
        }
        return null;
    }

    private String processPayOrder(long tableId,String userId,String tradeType,HttpServletRequest request){
        String orderId = null;
        String subOrderIds= null;
        Map<String,Object> orderMap =null;
        if(tableId>0){
            List<Long> subOrderList = newOrderService.getCurrentTableNoPaySubOrderId(userId);
            orderMap = newOrderService.getCurrentTableNoPayOrder(userId);
            //ParentOrderModel parentOrderModel = newOrderService.getLastByTableId(tableId);
            if(orderMap!=null){
                if(subOrderList!=null && subOrderList.size()>0){
                    for(int i=0;i<subOrderList.size();i++){
                        if(i==0){
                            subOrderIds= String.valueOf(subOrderList.get(i));
                        }else{
                            subOrderIds=subOrderIds+","+String.valueOf(subOrderList.get(i));
                        }
                    }
                }
                orderId=StrUtil.objectToString(orderMap.get("orderId"));
            }
        }

        log.info("userId:"+userId+",orderId:"+orderId);
        if(orderId==null || "".equals(orderId) || subOrderIds==null || "".equals(subOrderIds)){
            return null;
        }

        if("JSAPI".equals(tradeType)){
            if(userId==null || "".equals(userId)){
                return null;
            }
        }

        PayDetailModel pm = new PayDetailModel();
        pm.setOpenid(userId);
        pm.setAppid(AppSecretInfo.appId);
        pm.setOutTradeNo(orderId);

        PayDetailModel paySave = accessTokenService.savePayDetail(pm);

        if(paySave == null || paySave.getId()<=0){
            return null;
        }

        log.info("pay Id:"+paySave.getId());


        float price = Float.parseFloat(StrUtil.objectToString(orderMap.get("price")));
        log.info("price:"+price);
        if(price<=0){
            return null;
        }
        price =price*10*10;
        int priceInt = (int) price;

        String body = "智慧餐饮订单支付";
        String out_trade_no = String.valueOf(paySave.getId());
        //int total_fee = priceInt;//金额
        log.info("total money:"+priceInt);
        int total_fee = 1;
        String spbill_create_ip = RequestUtil.getIPAddress(request);//ip地址
        String trade_type = tradeType;//交易类型
        String product_id = AppSecretInfo.appId;
        String attach = orderId+"|"+subOrderIds;
        System.out.println("attach:"+attach);

        ScanPayReq scanReq = new ScanPayReq(body, out_trade_no, total_fee, spbill_create_ip, trade_type,product_id, attach, userId);
        Map<Object,Object> messageMap = ServerEngin.getInstance().unifiedOrder(scanReq);

        String pkg = "";
        if(messageMap!=null){
            String return_code = StrUtil.objectToString(messageMap.get("return_code"));
            String result_code = StrUtil.objectToString(messageMap.get("result_code"));
            if("SUCCESS".equals(return_code) && "SUCCESS".equals(result_code)){
                if("NATIVE".equals(tradeType)){
                   pkg = StrUtil.objectToString(messageMap.get("code_url"));
                }else {
                    String prepay_id = StrUtil.objectToString(messageMap.get("prepay_id"));
                    if (prepay_id != null && !"".equals(prepay_id)) {
                        pkg = "prepay_id=" + prepay_id;
                    }
                }
            }
        }

        if("".equals(pkg)){
            return null;
        }
        return pkg;
    }

    @RequestMapping("/payNotify")
    @ResponseBody
    public String payNotify(HttpServletRequest request){
        try{
            Map<String, String> requestMap = MessageParse.parseXml(request);

            if(requestMap!=null && "SUCCESS".equals(requestMap.get("result_code")) && "SUCCESS".equals(requestMap.get("return_code"))){

                String attach = requestMap.get("attach");
                String attachArr[] = attach.split("\\|");
                String outTradeNo="";
                String subOrderIds[] = null;
                if(attachArr.length>0){
                    outTradeNo=attachArr[0];
                    if(attachArr.length>1){
                        subOrderIds = attachArr[1].split(",");
                    }
                }
                String datetime= TimeUtil.getNowDateFormat("yyyy年MM月dd日 HH:mm");
                Long payTotal=Long.parseLong(requestMap.get("total_fee"));
                String payTotalConvert="";
                if(payTotal%100==0){
                    long pt = payTotal/100;
                    payTotalConvert=pt+"元";
                }else{
                    float pt = (float)payTotal/100;
                    payTotalConvert=pt+"元";
                }
                AccessTokenModel atm = accessTokenService.findByAppId(AppSecretInfo.appId);
                String accessToken = atm.getAccessToken();
                Map<Object,Object> notifyMsgMap = NotifyMsg.orderPayMsg(requestMap.get("openid"),payTotalConvert,datetime);
                ServerEngin.getInstance().sendTemplateMsg(accessToken,notifyMsgMap);
                log.info("save pay detail");
                PayDetailModel pm = new PayDetailModel();
                pm.setId(Integer.parseInt(requestMap.get("out_trade_no")));
                pm.setOpenid(requestMap.get("openid"));
                pm.setAppid(AppSecretInfo.appId);
                pm.setOutTradeNo(outTradeNo);
                pm.setMchId(requestMap.get("mch_id"));
                pm.setBankType(requestMap.get("bank_type"));
                pm.setTimeEnd(requestMap.get("time_end"));
                pm.setTotalFee(requestMap.get("total_fee"));
                pm.setTradeType(requestMap.get("trade_type"));
                pm.setTransactionId(requestMap.get("transaction_id"));

                accessTokenService.savePayDetail(pm);

                ParentOrderModel om = newOrderService.getParentOrderById(Long.parseLong(outTradeNo));
                if(om!=null) {
                    log.info(requestMap.get("openid")+","+om.getTableId());
                    newOrderService.updateOrderState(requestMap.get("openid"), om.getTableId(),subOrderIds);
                }


            }

        }catch(Exception e){
            log.error(e.getMessage());
        }
        ScanPayRes nrm = new ScanPayRes();
        nrm.setReturn_code("SUCCESS");
        nrm.setReturn_msg("OK");

        String msg = MessageParse.notifyReturnMessageToXml(nrm);
        System.out.println(msg);
        return msg;
    }

    @RequestMapping("/jsConfig")
    @ResponseBody
    public Map<Object,Object> jsApiConfig(String url){
        try{
            System.out.println(url);
            TicketModel ticketModel = accessTokenService.findTicketByAppId(AppSecretInfo.appId);
            Map<Object,Object> jsConfigMap = JsSign.sign(ticketModel.getTicket(), url,AppSecretInfo.appId);
            System.out.println("map:"+jsConfigMap);
            return jsConfigMap;
        }catch(Exception e){
            log.error(e.getMessage());
        }
        return null;
    }

    @RequestMapping("/menu")
    @ResponseBody
    public String menu(){
        try{
            //ProcessMsg pm = new ProcessMsg();
            return processMsg.menuMsg();
        }catch(Exception e){
            log.error(e.getMessage());
        }
        return "error";
    }

}
